package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.rooms.absrooms.AbsChessRoom;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.GridsUtils;
import java.util.ArrayList;
import java.util.List;

/**
 * 萨米板棋
 * 北欧传统棋种，国王逃脱版本
 */
public class SaamiTablutRoom extends AbsChessRoom {


    private final int THRONE_INDEX; //王座坐标索引
    private final int[] EXPORT_INDEXES; //四个出口坐标索引
    private static final int BLACK_SOLDIER = 1;  // 黑方小兵棋子
    private static final int WHITE_SOLDIER = 2;  // 白方小兵棋子
    private static final int WHITE_KING = 12;     // 白方国王棋子

    private List<Chess> chessList; //场上棋子集合
    private Chess choose; //当前选中的棋子

    private final List<int[]> moveArrayList = new ArrayList<>(); //棋子移动标记

    public SaamiTablutRoom(String roomName) {
        super(roomName, "萨米板棋，又名芬兰板棋，是北欧传统棋种。逆界上这款是国王角落逃脱版本。", "萨米板棋", GridsUtils.createEmptyGrids(9, 9), true, true);
        //王座在棋盘中间
        THRONE_INDEX = getIndex(curGrids.length/2, curGrids[0].length/2);
        //逃脱点在棋盘四角
        EXPORT_INDEXES = new int[4];
        EXPORT_INDEXES[0] = getIndex(0, 0);
        EXPORT_INDEXES[1] = getIndex(0, curGrids[0].length-1);
        EXPORT_INDEXES[2] = getIndex(curGrids.length-1, 0);
        EXPORT_INDEXES[3] = getIndex(curGrids.length-1, curGrids[0].length-1);
    }

    @Override
    public String getRuleText() {
        return "《萨米板棋规则》\n" +
                "【1】棋子和棋盘：\n" +
                "9x9方格棋盘，中心格是王座，四个角落格是逃脱点。\n" +
                "黑棋有16个小兵，白棋有1个国王8个小兵。\n" +
                "初始布局中，白棋国王位于王座，白棋小兵在国王四周呈十字形分布，黑棋小兵则以T字形分布在棋盘四周。\n" +
                "-\n" +
                "【2】移动规则：\n" +
                "黑棋先行，轮流行动，每方走一步。\n" +
                "棋子沿直线走任意格，不能越子，不能停留在有棋子的格子。\n" +
                "王座和逃脱点是国王专属格子，只有国王能够停留，其它棋子只可以路过不能停留。\n" +
                "-\n" +
                "【3】吃子规则：\n" +
                "己方主动移动小兵形成两枚己方小兵夹住一枚敌方小兵，吃掉对方该枚棋子。\n" +
                "己方主动移动小兵形成四枚己方棋子包住敌方国王，吃掉对方该枚棋子。\n" +
                "王座、四个逃脱点和棋盘边缘可以视作黑方棋子参与包围国王。\n" +
                "棋盘角落的空格可以视作移动方棋子参与夹击。\n" +
                "只有小兵能吃子，国王不能吃子，也不能参与夹子。\n" +
                "主动走进敌方棋子的包夹之中不会被吃。\n" +
                "-\n" +
                "【4】胜利条件：\n" +
                "对方无子可动，则立即胜利。\n" +
                "黑棋吃掉了白棋国王，立即胜利。\n" +
                "白棋国王走到4个逃脱点中任何一处，立即胜利。\n" +
                "-";
    }

    @Override
    public String getCoordMode() {
        return "31310000";
    }

    @Override
    public String getGameInfo() {
        // 先清空棋盘
        curGrids = GridsUtils.copyGrids(originGrids);
        signList.clear();

        // 特殊位置标记
        for (int exportIndex : EXPORT_INDEXES) {
            signList.add(new ColorSign(exportIndex, "#44666666"));
            signList.add(FigureSign.makeSingleFigure(exportIndex, "#55333333").setCorCenLine(1,1,1,1));
        }
        signList.add(new ColorSign(THRONE_INDEX, "#44FFCC00"));
        signList.add(FigureSign.makeSingleFigure(THRONE_INDEX, "#55333333").setAdjMidLine(1,1,1,1));
        signList.add(FigureSign.makeSingleFigure(THRONE_INDEX, "#55333333").setCorCenLine(1,1,1,1));

        // 根据chessList集合和choose对象来生成要显示到客户端的布局和标记
        if (chessList != null && chessList.size() > 0) {
            // 绘制棋子
            for (Chess chess : chessList) {
                curGrids[chess.row][chess.col] = chess.value;
            }

            // 绘制对弈时的选中棋子移动状态
            if (choose != null) {
                // 绘制棋子选中状态
                signList.add(new GroundSign(getIndex(choose.row, choose.col), ColorCost.TRANSPARENT, ColorCost.NEW_PUT_POINT, 2F, 0, 1));
                // 绘制棋子可移动路径
                List<int[]> canMovedPosList = getValidMovesForChess(choose);
                if (canMovedPosList.size() > 0) {
                    List<Integer> ids = new ArrayList<>();
                    for (int[] canMovedPos : canMovedPosList) {
                        ids.add(getIndex(canMovedPos[0], canMovedPos[1]));
                    }
                    signList.add(new ColorSign(ids, ColorCost.NEW_PUT_POINT_LIGHT));
                }
            }

            // 绘制移动箭头
            for (int[] moveArray : moveArrayList) {
                signList.add(new LineSign(moveArray[0], moveArray[1], ColorCost.MOVE_ARROW_LIGHT, 1));
            }
        }

        return super.getGameInfo();
    }

    @Override
    public void resetGrids() {
        super.resetGrids();
        chessList = null;
        choose = null;
        moveArrayList.clear();
    }

    @Override
    protected void onStartPrepare() {
        initChess();
        noticeBlackMove();
    }

    // 初始化棋子
    private void initChess() {
        chessList = new ArrayList<>();
        int centerRow = curGrids.length / 2;
        int centerCol = curGrids[0].length / 2;
        
        // 国王在王座
        chessList.add(new Chess(WHITE_KING, centerRow, centerCol));
        
        // 白兵十字形分布 - 8个兵，在国王四周呈十字分布
        // 内圈十字（距离国王1步）
        chessList.add(new Chess(WHITE_SOLDIER, centerRow-1, centerCol));
        chessList.add(new Chess(WHITE_SOLDIER, centerRow+1, centerCol));
        chessList.add(new Chess(WHITE_SOLDIER, centerRow, centerCol-1));
        chessList.add(new Chess(WHITE_SOLDIER, centerRow, centerCol+1));
        
        // 外圈十字（距离国王2步）
        chessList.add(new Chess(WHITE_SOLDIER, centerRow-2, centerCol));
        chessList.add(new Chess(WHITE_SOLDIER, centerRow+2, centerCol));
        chessList.add(new Chess(WHITE_SOLDIER, centerRow, centerCol-2));
        chessList.add(new Chess(WHITE_SOLDIER, centerRow, centerCol+2));
        
        // 黑兵T字形分布在四周
        // 上方T字
        for (int col = 3; col <= 5; col++) {
            chessList.add(new Chess(BLACK_SOLDIER, 0, col));
        }
        chessList.add(new Chess(BLACK_SOLDIER, 1, 4));
        
        // 下方T字
        for (int col = 3; col <= 5; col++) {
            chessList.add(new Chess(BLACK_SOLDIER, 8, col));
        }
        chessList.add(new Chess(BLACK_SOLDIER, 7, 4));
        
        // 左侧T字
        for (int row = 3; row <= 5; row++) {
            chessList.add(new Chess(BLACK_SOLDIER, row, 0));
        }
        chessList.add(new Chess(BLACK_SOLDIER, 4, 1));
        
        // 右侧T字
        for (int row = 3; row <= 5; row++) {
            chessList.add(new Chess(BLACK_SOLDIER, row, 8));
        }
        chessList.add(new Chess(BLACK_SOLDIER, 4, 7));
    }

    @Override
    public void doRule(int row, int col, int value) {
        // 还未选择目标时
        if (choose == null) {
            Chess chess = getChessByPos(row, col);
            if (chess != null && chess.isSameSide(value)) {
                choose = chess;
                noticeAllRefreshGameInfo();
            }
        }
        // 已经选中棋子了
        else {
            List<int[]> canMovedPos = getValidMovesForChess(choose);
            boolean canMove = false;
            for (int[] move : canMovedPos) {
                if (move[0] == row && move[1] == col) {
                    canMove = true;
                    break;
                }
            }
            
            if (canMove) {
                doChessMove(row, col);
            }
            else {
                Chess chess = getChessByPos(row, col);
                if (chess != null && chess.isSameSide(value)) {
                    choose = chess;
                    noticeAllRefreshGameInfo();
                }
                else {
                    choose = null;
                    noticeAllRefreshGameInfo();
                }
            }
        }
    }

    // 获取指定棋子的合法移动
    private List<int[]> getValidMovesForChess(Chess chess) {
        List<int[]> moves = new ArrayList<>();
        int fromRow = chess.row;
        int fromCol = chess.col;
        
        // 检查四个方向：上下左右
        int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        
        for (int[] direction : directions) {
            int toRow = fromRow + direction[0];
            int toCol = fromCol + direction[1];
            
            // 沿着这个方向一直检查到边界
            while (toRow >= 0 && toRow < curGrids.length && toCol >= 0 && toCol < curGrids[0].length) {
                if (isValidMoveForChess(chess, toRow, toCol)) {
                    moves.add(new int[]{toRow, toCol});
                } else {
                    break; // 遇到阻挡就停止这个方向
                }
                toRow += direction[0];
                toCol += direction[1];
            }
        }
        
        // 对于小兵，移除国王专属格子
        if (chess.value != WHITE_KING) {
            moves.removeIf(move -> {
                int index = getIndex(move[0], move[1]);
                return index == THRONE_INDEX || isExportIndex(index);
            });
        }
        
        return moves;
    }

    // 检查棋子是否能移动到指定位置
    private boolean isValidMoveForChess(Chess chess, int toRow, int toCol) {
        // 不能移动到原地
        if (chess.row == toRow && chess.col == toCol) {
            return false;
        }
        
        // 目标位置必须为空
        if (getChessByPos(toRow, toCol) != null) {
            return false;
        }
        
        // 检查路径是否清晰
        if (!isPathClearForChess(chess, toRow, toCol)) {
            return false;
        }
        
        // 小兵可以跨越国王专属格子，不需要在这里阻止
        // 王座和逃脱点的限制将在getValidMovesForChess方法中处理
        return true;
    }

    // 检查路径是否清晰
    private boolean isPathClearForChess(Chess chess, int toRow, int toCol) {
        int rowStep = Integer.compare(toRow - chess.row, 0);
        int colStep = Integer.compare(toCol - chess.col, 0);
        
        int currentRow = chess.row + rowStep;
        int currentCol = chess.col + colStep;
        
        // 检查路径上的每个格子（不包括起点和终点）
        while (currentRow != toRow || currentCol != toCol) {
            if (getChessByPos(currentRow, currentCol) != null) {
                return false; // 路径上有阻挡
            }
            currentRow += rowStep;
            currentCol += colStep;
        }
        
        return true;
    }

    // 执行棋子移动
    private void doChessMove(int toRow, int toCol) {
        int fromRow = choose.row;
        int fromCol = choose.col;
        
        // 记录移动箭头
        moveArrayList.clear();
        moveArrayList.add(new int[]{getIndex(fromRow, fromCol), getIndex(toRow, toCol)});
        
        // 执行移动
        choose.row = toRow;
        choose.col = toCol;
        
        // 处理吃子
        handleCaptures(choose);
        
        // 检查游戏结束
        checkGameEnd();

        // 清除选中状态
        choose = null;
        
        // 切换玩家 - 根据当前行动方切换
        if (cur == 1) {
            noticeWhiteMove();
        } else {
            noticeBlackMove();
        }
    }

    // 处理吃子
    private void handleCaptures(Chess movedChess) {
        // 只有小兵能吃子，国王不能吃子
        if (movedChess.value == WHITE_KING) {
            System.out.println("国王移动，不检查吃子");
            return;
        }
        
        List<Chess> capturedChesses = new ArrayList<>();
        
        System.out.println("=== 开始检查夹击吃子 ===");
        System.out.println("移动棋子: row=" + movedChess.row + ", col=" + movedChess.col + ", side=" + movedChess.getSide());
        
        // 检查移动棋子上下左右四个相邻格子
        int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        
        for (int[] direction : directions) {
            int checkRow = movedChess.row + direction[0];
            int checkCol = movedChess.col + direction[1];
            
            System.out.println("检查相邻格子: row=" + checkRow + ", col=" + checkCol);
            
            // 检查相邻格子是否在棋盘内
            if (checkRow < 0 || checkRow >= curGrids.length || checkCol < 0 || checkCol >= curGrids[0].length) {
                System.out.println("  相邻格子超出边界");
                continue;
            }
            
            Chess adjacentChess = getChessByPos(checkRow, checkCol);
            if (adjacentChess == null) {
                System.out.println("  相邻格子为空");
                continue;
            }
            
            // 检查是否是对方棋子
            if (adjacentChess.isSameSide(movedChess.getSide())) {
                System.out.println("  相邻格子是己方棋子");
                continue;
            }
            
            System.out.println("  发现对方棋子: " + adjacentChess.value);
            
            // 根据棋子类型处理不同的吃子逻辑
            if (adjacentChess.value == WHITE_KING) {
                // 检查国王是否被包围
                if (isKingCaptured()) {
                    System.out.println("  国王被包围，将被吃掉");
                    capturedChesses.add(adjacentChess);
                }
            } else {
                // 检查对方小兵是否被夹击
                Chess captured = checkSoldierSandwich(movedChess, adjacentChess, direction);
                if (captured != null) {
                    System.out.println("  对方小兵被夹击，将被吃掉");
                    capturedChesses.add(captured);
                }
            }
        }
        
        System.out.println("总共捕获棋子数量: " + capturedChesses.size());
        
        // 移除被吃的棋子
        for (Chess captured : capturedChesses) {
            chessList.remove(captured);
            System.out.println("移除被吃棋子: row=" + captured.row + ", col=" + captured.col);
        }
        
        System.out.println("=== 夹击吃子检查结束 ===");
    }


    // 检查对方小兵是否被夹击
    private Chess checkSoldierSandwich(Chess movedChess, Chess targetChess, int[] direction) {
        System.out.println("  --- 检查小兵夹击条件 ---");
        System.out.println("  目标小兵: row=" + targetChess.row + ", col=" + targetChess.col);

        // 检查目标小兵的另一侧是否有己方支持
        int supportRow = targetChess.row + direction[0];
        int supportCol = targetChess.col + direction[1];

        System.out.println("  检查支持位置: row=" + supportRow + ", col=" + supportCol);

        // 检查支持位置是否超出边界
        if (supportRow < 0 || supportRow >= curGrids.length || supportCol < 0 || supportCol >= curGrids[0].length) {
            System.out.println("  支持位置超出边界，无支持");
            return null; // 边界不能提供支持
        }

        // 检查支持位置是否有己方棋子（只能是己方小兵，国王不能参与夹子）
        Chess supportChess = getChessByPos(supportRow, supportCol);
        if (supportChess != null && supportChess.value != WHITE_KING && supportChess.isSameSide(movedChess.getSide())) {
            System.out.println("  支持位置有己方小兵");
            return targetChess;
        }

        // 检查支持位置是否是逃脱点（可以视作支持）
        int supportIndex = getIndex(supportRow, supportCol);
        if (supportChess == null && isExportIndex(supportIndex)) {
            System.out.println("  支持位置是逃脱点，视作有支持");
            return targetChess;
        }

        System.out.println("  无己方支持，不能被夹击");
        return null;
    }

    // 检查夹击吃子
    private Chess checkSandwichCapture(Chess movedChess, int[] direction) {
        // 只有小兵能吃子，国王不能吃子
        if (movedChess.value == WHITE_KING) {
            System.out.println("  国王不能吃子");
            return null;
        }
        
        int opponentSide = (movedChess.getSide() == 1) ? 2 : 1;
        
        System.out.println("  --- 检查夹击条件 ---");
        System.out.println("  移动棋子side: " + movedChess.getSide() + ", 对手side: " + opponentSide);
        
        // 检查反方向是否有己方棋子或角落空格（只能是己方小兵，国王不能参与夹子）
        int backRow = movedChess.row - direction[0];
        int backCol = movedChess.col - direction[1];
        
        System.out.println("  反方向位置: row=" + backRow + ", col=" + backCol);
        
        // 检查反方向是否超出边界（棋盘角落）
        if (backRow < 0 || backRow >= curGrids.length || backCol < 0 || backCol >= curGrids[0].length) {
            // 如果是角落边界，可以视作移动方棋子参与夹击
            System.out.println("  反方向是角落边界，视作移动方棋子");
            return null; // 但还需要检查正方向是否有对方棋子
        }
        
        Chess backChess = getChessByPos(backRow, backCol);
        boolean hasBackSupport = false;
        
        // 反方向必须是己方小兵（国王不能参与夹子）
        if (backChess != null && backChess.value != WHITE_KING && backChess.isSameSide(movedChess.getSide())) {
            hasBackSupport = true;
            System.out.println("  反方向有己方棋子: " + backChess.value);
        }
        
        // 检查是否是角落空格（可以视作移动方棋子）
        int backIndex = getIndex(backRow, backCol);
        if (!hasBackSupport && (backIndex == 0 || backIndex == 8 || backIndex == 72 || backIndex == 80)) {
            if (backChess == null) {
                hasBackSupport = true;
                System.out.println("  反方向是角落空格，视作移动方棋子");
            }
        }
        
        if (!hasBackSupport) {
            System.out.println("  反方向无己方小兵支持");
            return null;
        }
        
        // 检查正方向是否有对方棋子（只能是小兵，不能吃国王）
        int frontRow = movedChess.row + direction[0];
        int frontCol = movedChess.col + direction[1];
        
        System.out.println("  正方向位置: row=" + frontRow + ", col=" + frontCol);
        
        // 检查正方向是否超出边界（棋盘角落）
        if (frontRow < 0 || frontRow >= curGrids.length || frontCol < 0 || frontCol >= curGrids[0].length) {
            System.out.println("  正方向是角落边界，无对方棋子");
            return null; // 角落边界不能有对方棋子
        }
        
        Chess frontChess = getChessByPos(frontRow, frontCol);
        if (frontChess != null && frontChess.getSide() == opponentSide && frontChess.value != WHITE_KING) {
            System.out.println("  发现可吃棋子: " + frontChess.value);
            return frontChess;
        }
        
        System.out.println("  正方向无对方小兵或条件不满足");
        return null;
    }

    // 检查国王是否逃脱
    private boolean checkKingEscape() {
        Chess king = getKing();
        if (king == null) return false;
        
        // 检查国王是否在逃脱点上
        int kingIndex = getIndex(king.row, king.col);
        return isExportIndex(kingIndex);
    }

    // 检查是否是出口索引
    private boolean isExportIndex(int index) {
        for (int exportIndex : EXPORT_INDEXES) {
            if (index == exportIndex) {
                return true;
            }
        }
        return false;
    }

    // 检查游戏结束条件
    private void checkGameEnd() {
        // 检查国王是否逃脱
        if (checkKingEscape()) {
            doOver(WinMode.WHITE_WIN, "白方国王成功逃脱！");
            return;
        }
        
        // 检查国王是否被捕获
        if (getKing() == null) {
            doOver(WinMode.BLACK_WIN, "黑方成功捕获国王！");
            return;
        }
        
        // 检查是否无子可动（和棋,正常不可能）
        if (!hasValidMoves(1) && !hasValidMoves(2)) {
            String winner, loser;
            if (cur == 1) {
                winner = player_black.getNickNameOrTemp();
                loser = player_white.getNickNameOrTemp();
                doOver(WinMode.BLACK_WIN, winner + "获胜，" + loser + "无子可动！");
            } else {
                winner = player_white.getNickNameOrTemp();
                loser = player_black.getNickNameOrTemp();
                doOver(WinMode.WHITE_WIN, winner + "获胜，" + loser + "无子可动！");
            }
        }
    }

    // 获取国王
    private Chess getKing() {
        for (Chess chess : chessList) {
            if (chess.value == WHITE_KING) {
                return chess;
            }
        }
        return null;
    }

    // 检查国王是否被包围
    private boolean isKingCaptured() {
        Chess king = getKing();
        if (king == null) return false;
        
        System.out.println("=== 检查国王是否被包围 ===");
        System.out.println("国王位置: row=" + king.row + ", col=" + king.col);
        
        // 检查四个邻格是否被包围
        int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        int surroundedCount = 0;
        int totalNeighbors = 0;
        
        for (int[] direction : directions) {
            int neighborRow = king.row + direction[0];
            int neighborCol = king.col + direction[1];
            
            System.out.println("检查邻居: row=" + neighborRow + ", col=" + neighborCol);
            
            if (neighborRow >= 0 && neighborRow < curGrids.length && 
                neighborCol >= 0 && neighborCol < curGrids[0].length) {
                totalNeighbors++;
                Chess neighborChess = getChessByPos(neighborRow, neighborCol);
                int neighborIndex = getIndex(neighborRow, neighborCol);
                
                // 检查是否是黑方棋子，或者特殊位置（王座、逃脱点）
                boolean isBlackControl = false;
                
                if (neighborChess != null && neighborChess.getSide() == 1) {
                    isBlackControl = true;
                    System.out.println("  邻居是黑方棋子");
                } else if (neighborIndex == THRONE_INDEX || isExportIndex(neighborIndex)) {
                    // 王座和逃脱点视作黑方控制
                    isBlackControl = true;
                    System.out.println("  邻居是特殊位置（王座或逃脱点）");
                }
                
                if (isBlackControl) {
                    surroundedCount++;
                }
            } else {
                // 超出边界也视作被包围（棋盘边缘）
                System.out.println("  邻居超出边界，视作被包围");
                surroundedCount++;
            }
        }
        
        System.out.println("被包围的邻居数: " + surroundedCount + "/" + totalNeighbors);
        
        // 需要四个方向都被包围
        return surroundedCount == 4;
    }

    // 检查指定玩家是否有合法移动
    private boolean hasValidMoves(int side) {
        for (Chess chess : chessList) {
            if (chess.getSide() == side) {
                List<int[]> moves = getValidMovesForChess(chess);
                if (!moves.isEmpty()) {
                    return true;
                }
            }
        }
        return false;
    }

    // 根据位置获取棋子
    private Chess getChessByPos(int row, int col) {
        for (Chess chess : chessList) {
            if (chess.row == row && chess.col == col) {
                return chess;
            }
        }
        return null;
    }

    // 棋子类
    private static class Chess {
        int value;
        int row;
        int col;
        
        Chess(int value, int row, int col) {
            this.value = value;
            this.row = row;
            this.col = col;
        }
        
        int getSide() {
            return (value == BLACK_SOLDIER) ? 1 : 2;
        }
        
        boolean isSameSide(int side) {
            return getSide() == side;
        }
        
        String getColor() {
            return getSide() == 1 ? ColorCost.BLACK : ColorCost.WHITE;
        }
    }
}


